﻿using System;
using System.Text.RegularExpressions; 

namespace QuickUIT.Utilities
{
    /// <summary>
    /// Provides simple methods for validating parameters/arguments. 
    /// </summary>
    public static class ValidationUtility
    {
        /// <summary>
        /// Validates an argument is not null. 
        /// </summary>
        /// <param name="parameter">The parameter to validate.</param>
        /// <param name="parameterName">The name of the parameter.</param>
        /// <exception cref="ArgumentNullException">Thrown if argument is null.</exception>
        public static void ValidateArgumentNotNull(object parameter, string parameterName)
        {
            ValidateArgumentNotNull(parameter, parameterName, String.Format("The parameter '{0}' cannot be null.", parameterName)); 
        }

        /// <summary>
        /// Validates an argument argument is not null. 
        /// </summary>
        /// <param name="parameter">The parameter to validate.</param>
        /// <param name="parameterName">The name of the parameter.</param>
        /// <param name="message">The exception message.</param>
        /// <exception cref="ArgumentNullException">Thrown if argument is null.</exception>
        public static void ValidateArgumentNotNull(object parameter, string parameterName, string message)
        {
            if (parameter == null)
            {
                throw new ArgumentNullException(parameterName, message); 
            }
        }

        /// <summary>
        /// Validates a string argument is not null, empty, or contains only whitespace. 
        /// </summary>
        /// <param name="parameter">The parameter to validate.</param>
        /// <param name="parameterName">The name of the parameter.</param>
        /// <exception cref="ArgumentException">Thrown if argument is null, empty, or contains only whitespace.</exception>
        public static void ValidateStringNotNullOrEmptyOrWhitespace(string parameter, string parameterName)
        {
            ValidateStringNotNullOrEmptyOrWhitespace(parameter, parameterName, String.Format("The string parameter '{0}' cannot be null, empty or contain only whitespace.", parameterName)); 
        }

        /// <summary>
        /// Validates a string argument is not null, empty, or contains only whitespace. 
        /// </summary>
        /// <param name="parameter">The parameter to validate.</param>
        /// <param name="parameterName">The name of the parameter.</param>
        /// <param name="message">The exception message.</param>
        /// <exception cref="ArgumentException">Thrown if argument is null, empty, or contains only whitespace.</exception>
        public static void ValidateStringNotNullOrEmptyOrWhitespace(string parameter, string parameterName, string message)
        {
            var regex = new Regex(@"^\s*$");
            if (parameter == null || regex.IsMatch(parameter))
            {
                throw new ArgumentException(parameterName, message); 
            }
        }

        /// <summary>
        /// Validates that a value is greater than a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        public static void ValidateValueGreaterThan(int value, int expectedValue, string parameterName)
        {
            ValidateValueGreaterThan(value, expectedValue, parameterName, String.Format("The value parameter '{0}' with value '{1}' must be greater than '{2}'", parameterName, value, expectedValue)); 
        }

        /// <summary>
        /// Validates that a value is greater than a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        /// <param name="message">The exception message.</param>
        public static void ValidateValueGreaterThan(int value, int expectedValue, string parameterName, string message)
        {
            ValidateArgumentNotNull(value, "value");
            ValidateArgumentNotNull(expectedValue, "expectedValue");
            if (value <= expectedValue)
            {
                throw new ArgumentException(parameterName, message); 
            }
        }

        /// <summary>
        /// Validates that a value is greater than or equal to a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        public static void ValidateValueGreaterThanOrEqualTo(int value, int expectedValue, string parameterName)
        {
            ValidateValueGreaterThanOrEqualTo(value, expectedValue, parameterName, String.Format("The value parameter '{0}' with value '{1}' must be greater than or equal to '{2}'", parameterName, value, expectedValue)); 
        }

        /// <summary>
        /// Validates that a value is greater than or equal to a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        /// <param name="message">The exception message.</param>
        public static void ValidateValueGreaterThanOrEqualTo(int value, int expectedValue, string parameterName, string message)
        {
            ValidateArgumentNotNull(value, "value");
            ValidateArgumentNotNull(expectedValue, "expectedValue");
            if (value < expectedValue)
            {
                throw new ArgumentException(parameterName, message);
            }
        }

        /// <summary>
        /// Validates that a value is Less than a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        public static void ValidateValueLessThan(int value, int expectedValue, string parameterName)
        {
            ValidateValueLessThan(value, expectedValue, parameterName, String.Format("The value parameter '{0}' with value '{1}' must be less than '{2}'", parameterName, value, expectedValue));
        }

        /// <summary>
        /// Validates that a value is Less than a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        /// <param name="message">The exception message.</param>
        public static void ValidateValueLessThan(int value, int expectedValue, string parameterName, string message)
        {
            ValidateArgumentNotNull(value, "value");
            ValidateArgumentNotNull(value, "expectedValue");
            if (value >= expectedValue)
            {
                throw new ArgumentException(parameterName, message);
            }
        }

        /// <summary>
        /// Validates that a value is Less than or equal to a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        public static void ValidateValueLessThanOrEqualTo(int value, int expectedValue, string parameterName)
        {
            ValidateValueLessThanOrEqualTo(value, expectedValue, parameterName, String.Format("The value parameter '{0}' with value '{1}' must be less than or equal to '{2}'", parameterName, value, expectedValue));
        }

        /// <summary>
        /// Validates that a value is Less than or equal to a specified value.  
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="expectedValue">The value to compare the value against.</param>
        /// <param name="parameterName">The name of the value parameter.</param>
        /// <param name="message">The exception message.</param>
        public static void ValidateValueLessThanOrEqualTo(int value, int expectedValue, string parameterName, string message)
        {
            ValidateArgumentNotNull(value, "value");
            ValidateArgumentNotNull(expectedValue, "expectedValue");
            if (value > expectedValue)
            {
                throw new ArgumentException(parameterName, message);
            }
        }

        /// <summary>
        /// Validates that a number is within a range (inclusive). 
        /// </summary>
        /// <param name="number">The number to validate.</param>
        /// <param name="min">The minimum value of the range.</param>
        /// <param name="max">The maximum value of the range.</param>
        /// <param name="parameterName">The name of the parameter.</param>
        public static void ValidateValueInRangeInclusive(double number, double min, double max, string parameterName)
        {
            ValidateValueInRangeInclusive(number, min, max, parameterName, String.Format("The number parameter '{0}' with value '{1}' must be between '{2}' and '{3}'.", parameterName, number, min, max));    
        }

        /// <summary>
        /// Validates that a number is within a range (inclusive). 
        /// </summary>
        /// <param name="number">The number to validate.</param>
        /// <param name="min">The minimum value of the range.</param>
        /// <param name="max">The maximum value of the range.</param>
        /// <param name="parameterName">The name of the parameter.</param>
        /// <param name="message">The exception message.</param>
        public static void ValidateValueInRangeInclusive(double number, double min, double max, string parameterName, string message)
        {
            if (number < min)
            {
                throw new ArgumentOutOfRangeException(parameterName, message);
            }
            if (number > max)
            {
                throw new ArgumentOutOfRangeException(parameterName, message);
            }
        }
    }
}
